package com.android.flowoflife;

import java.io.IOException;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.Process;
import android.os.PowerManager.WakeLock;
import android.util.Log;

import com.android.flowoflife.hardware.ICameraAccess;
import com.android.flowoflife.hardware.StorageAccess;

public class PhotoService extends Service {
	NotificationManager mNM;
	
	private static WakeLock wakeLock;
	private static boolean isRunning = false;

	private CameraAccessShutterCallback shutterCallback;
	private CameraAccessRawPictureCallback rawPictureCallback;
	private CameraAccessJPEGPictureCallback jpegPictureCallback;
	
	private StorageAccess storageAccess;
	private ICameraAccess cameraAccess;

	private int captureFrameCount = 0;
	
	@Override
	public void onCreate() {
		mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
		showNotification();
	}

	@Override
	public void onStart(final Intent intent, int startId) {
		super.onStart(intent, startId);
		boolean stopService = intent.getBooleanExtra(IFlowOfLifeConstants.STOP_SERVICE, false);
		if (stopService){
			stopSelf();
			return;
		}
		synchronized (this.getClass()) {
			if(!isRunning){
				acquireWakeLock(this);
				isRunning = true;
				// start photo shooting in new thread
				new Thread(){

					@Override
					public void run() {
						Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
						captureFrameCount += 1;
						try{
							if (cameraAccess.lock()) {
								cameraAccess.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);
							}
						}catch (Exception e) {
							
						}finally{
							stopSelf();
							Alarms.scheduleNextPhotoshoot(PhotoService.this);
							isRunning = false;
							releaseWakeLock(PhotoService.this);
						}
					}
					
				}.start();
			}else{
				Log.d(IFlowOfLifeConstants.LOG_TAG, "Service is running");
			}
			
		}
	}

	
	@Override
	public void onDestroy() {
		mNM.cancel(R.string.photo_service_started);
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	private static void acquireWakeLock(Context context) {
		if (wakeLock == null) {
			PowerManager powerManager = (PowerManager) context
					.getSystemService(POWER_SERVICE);
			wakeLock = powerManager.newWakeLock(
					PowerManager.PARTIAL_WAKE_LOCK, "PhotoService wakelock");
		}
		wakeLock.acquire();
	}

	private static void releaseWakeLock(Context context) {
		wakeLock.release();
	}
	
	/**
     * Show a notification while this service is running.
     */
    private void showNotification() {
        CharSequence text = getText(R.string.service_start);

        // Set the icon, scrolling text and timestamp
        Notification notification = new Notification(R.drawable.stat_sample, text,
                System.currentTimeMillis());

        // The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, Main.class), 0);

        // Set the info for the views that show in the notification panel.
        notification.setLatestEventInfo(this, getText(R.string.photo_service_label),
                       text, contentIntent);

        // Send the notification.
        // We use a layout id because it is a unique number.  We use it later to cancel.
        mNM.notify(R.string.photo_service_started, notification);
    }
	
	class CameraAccessJPEGPictureCallback implements PictureCallback {
		@Override
		public void onPictureTaken(byte[] data, Camera camera) {
			try {
        		storageAccess.writeIntoExternalMemory(captureFrameCount, data);
        	} catch (IOException emioe) {
        		Log.e(IFlowOfLifeConstants.LOG_TAG, "External memory error", emioe);
        		
        		try {
	        		storageAccess.writeIntoInternalMemory(captureFrameCount, data);
	        	} catch (IOException imioe) {
	        		Log.e(IFlowOfLifeConstants.LOG_TAG, "Internal memory error", imioe);
	        	}
        	}
        	
        	cameraAccess.release();
		}		
	}
	
	class CameraAccessShutterCallback implements ShutterCallback {
		@Override
		public void onShutter() {
		}		
	}
	
	class CameraAccessRawPictureCallback implements PictureCallback {
		@Override
		public void onPictureTaken(byte[] data, Camera camera) {			
		}		
	}

}
